import * as THREE from 'three';
import { CSS2DObject, CSS2DRenderer } from './assert/js/CSS2DRenderer'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import ColladaLoader from './assert/js/ColladaLoader'

import './show'
import { Mesh } from 'three';

import dataShow from './data_show'


const debug = true
const scene = new THREE.Scene();
/**
 * 创建网格模型
 */
// 辅助坐标系 
// if (debug) {
//   var axes = new THREE.AxesHelper(1000);
//   scene.add(axes);
// }

const loader = new ColladaLoader();

let qs = {}
  ; (() => {
    const query = window.location.search.substring(1);
    let res = {}
    const vars = query.split("&");
    for (let i = 0; i < vars.length; i++) {
      var pair = vars[i].split("=");
      res[pair[0]] = pair[1]
    }
    qs = res
  })()
let fillStyleMap = {
  '自持': '#cccccc',
  '公寓': '#cccccc',
  '公租': '#cccccc',
  '物业': '#cccccc',
  '商业': '#cccccc',
  '办公': '#cccccc',
  '已开': '#cccccc',
  '未开': '#bcdabe',
  '预计': '#4da5ff',
  '本期': '#fdab71'

}

let groupArr
let dy, dx
let fov = 50, near = 1, fear = 3000, json
let mesh = null
let loadUrl, colorUrl
let ambLight, light, plane
// 颜色常量
let color45 = new THREE.Color(0x50ba57); //代表噪音在45以内用的颜色
let color50 = new THREE.Color(0x75cd67);
let color55 = new THREE.Color(0xcbe47c);
let color60 = new THREE.Color(0xf3eaa7);
let color65 = new THREE.Color(0xf3d0a8);
let color70 = new THREE.Color(0xffb3a7);
let colorWorse = new THREE.Color(0xfff8181);
let color
let colors = [];
let normals;
let buildUnitMap;
let numStrArr
let animHandler


//设置建筑名称
$('.build_name').html(decodeURI(qs.building.trim()))
const getDaeUrl = (dae, prefix) => `https://${prefix}/dae/${dae}.dae`
let splits = qs.dae.trim().split(',')
let prefix = qs.prefix.trim()
if (splits.length === 1) {
  //只有一个楼栋
  loadUrl = getDaeUrl(splits[0], prefix)
} else {
  loadUrl = splits.map(function (s) {
    const [t, u] = s.split('-')
    return {
      t: decodeURI(t),
      u: getDaeUrl(u, prefix)
    }
  }
  )
}


if (debug) {
  loadUrl = [
    { t: '南区', u: `assert/dae/10.dae` },
    { t: '北区', u: `assert/dae/噪声没路的模型.dae` }
  ]
  loadUrl = `assert/dae/揽月阁.dae`
  colorUrl = `assert/json/揽月阁.json`
} else {
  console.log = () => { }
  colorUrl = `${qs.url.trim()}?code=${qs.code.trim()}`
}
//根据模型数，显示ui
const $daes = $('#daes')
if (loadUrl instanceof Array) {
  $daes.show()
  loadDae(loadUrl[0].u)
  loadUrl.forEach(({ t }) => {
    $daes.append(`<span>${t}</span>`)
  })

} else {
  loadDae(loadUrl)
  $daes.hide()
}

function noiseToColor(noise) {
  if (noise <= 45) {
    return color45
  } else if (noise <= 50) {
    return color50
  } else if (noise <= 55) {
    return color55
  } else if (noise <= 60) {
    return color60
  } else if (noise <= 65) {
    return color65
  } else if (noise <= 70) {
    return color70
  } else {
    return colorWorse
  }
}
function correctArr(numStrArr) { //修改处5，新增方法，对特殊数组处理
  if (numStrArr.length == 5) { //数组有5个元素时前两个数字代表楼号
    numStrArr[0] = numStrArr[0] + "-" + numStrArr[1]
    numStrArr[1] = numStrArr[2]
    numStrArr[2] = numStrArr[3]
    numStrArr[3] = numStrArr[4]
  }
  return numStrArr
}

function setNoiseColor(isDaytime) {
  let vertexMaterial = new THREE.MeshStandardMaterial({
    side: THREE.DoubleSide, //两个三角面均可见
    vertexColors: true,
  }); //材质对象
  for (let a = 0; a < groupArr.length; a++) {
    if (groupArr[a].name.search("-") != -1) { //筛选出name包含"-"的元素
      numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

      try {
        normals = groupArr[a].children[0].geometry.attributes.normal.array //每个顶点所在面的法向量数组，每3个数字表示一个顶点
        colors = new Array(normals.length); //颜色数组数量需要和顶点个数保持一致，每3个数字表示一个颜色
        colors.fill(0.6) //楼面默认填充灰色
        let arr = json.data.find(item => item.name === numStrArr[0] + "#").data.reduce(function (a, b) { return a.concat(b) }); //二维数组变一维数组
        let houseData = arr[buildUnitMap.get(numStrArr[0]).indexOf(numStrArr[1] + "-" + numStrArr[2])][parseInt(numStrArr[3]) - 1] //先通过楼号从hash表中拿到数组，name中间两个数字在数组的索引就代表第几列
        if (houseData != null) {
          if (isDaytime) {
            if (houseData.noise2 != undefined) {
              color = noiseToColor(houseData.noise2)
            }
          } else {
            if (houseData.noise1 != undefined) {
              color = noiseToColor(houseData.noise1)
            }
          }
          for (let i = 0; i < normals.length; i += 3) {
            colors[i] = color.r
            colors[i + 1] = color.g
            colors[i + 2] = color.b
          }
          groupArr[a].children[0].geometry.attributes.color = new THREE.Float32BufferAttribute(colors, 3);
          // 三角面(网格)渲染模式
          groupArr[a].children[0].material = vertexMaterial
        }
      } catch (error) {
        continue
      }

    }
    renderer.info.reset()
  }


}

function loadDae(url) {
  //加载动画
  $('#loading_mask').show()
  //移除渲染
  window.cancelAnimationFrame(animHandler)
  animHandler = -1
  //移除之前的模型
  if (mesh) {
    console.log(mesh)
    scene.clear()
    reset()
    scene.add(light)
    scene.add(ambLight)
    scene.add(plane)
  }
  

  // 添加模型
  loader.load(url, result => {

    mesh = result.scene
    let box = new THREE.Box3().setFromObject(mesh);  // 定位  
    mesh.rotation.x = - 0 / 180 * Math.PI //x轴对齐
    mesh.rotation.y = - 0 / 180 * Math.PI
    mesh.rotation.z = 90 / 180 * Math.PI
    let mdwid = box.max.x - box.min.x;
    let mdHei = box.max.z - box.min.z;
    dy = mdwid / 2 + box.min.x
    dx = mdHei / 2 + box.min.z

    mesh.position.set(-dx, -dy)
    mesh.receiveShadow = true
    // mesh.material.depthTest = false
    mesh.children[0].receiveShadow = true
    //显示道路阴影
    for (let item of mesh.children[0].children) {
      // console.log(item)
      if (item.name && item.name.indexOf('-') == -1 && item.name.indexOf("instance") == -1) {
        item.children.forEach(ii => {

          if (ii instanceof Mesh) {

            ii.geometry.computeBoundingSphere()
            const { z } = ii.geometry.boundingSphere.center

            if (z) return
            ii.castShadow = true
            ii.receiveShadow = true
            ii.material.opacity = 1
            ii.material.transparent = false
            console.log(ii, ii.material.color)
            // let colorMaterial = new THREE.MeshStandardMaterial({
            //   side: THREE.BackSide, //两个三角面均可见
            // }); //材质对象
            // let color = new THREE.Color(0x666666)
            // ii.material = colorMaterial
            // ii.material.color = color
            // ii.material.depthWrite = true
          }

        })


      } else {

        // console.log(item.name)
      }

    }
    groupArr = result.scene.children[0].children

    var buildTopFloors = new Map //楼号-最高层数的散列表
    for (var a = 0; a < groupArr.length; a++) {
      if (groupArr[a].name.search("-") != -1) {
        numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

        if (buildTopFloors.get(numStrArr[0]) == null) {
          buildTopFloors.set(numStrArr[0], numStrArr[3])
        } else {
          if (parseInt(numStrArr[3]) > parseInt(buildTopFloors.get(numStrArr[0]))) {
            buildTopFloors.set(numStrArr[0], numStrArr[3])
          }
        }
      }
    }
    buildUnitMap = new Map()
    buildTopFloors.forEach(function (value, key) {
      buildUnitMap.set(key, [])
    })
    for (var a = 0; a < groupArr.length; a++) {
      if (groupArr[a].name.search("-") != -1) {
        numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

        if (numStrArr[3] == "1") {
          if (buildUnitMap.get(numStrArr[0]).indexOf(numStrArr[1] + "-" + numStrArr[2]) == -1) {
            buildUnitMap.get(numStrArr[0]).push(numStrArr[1] + "-" + numStrArr[2])
          }
        }
      }
    }
    buildUnitMap.forEach(function (value) {
      value.sort()
    })
    let promise
    console.log("colorUrl", colorUrl, json)
    if (!json) {
      promise = fetch(colorUrl)
    } else {
      promise = new Promise((r) => r(json))
    }

    promise.then(async res => {
      if (!json) {
        json = await res.json()
      }
      setNoiseColor(true)
      buildNoPositionMap.forEach((value, key) => {
        console.log(json)
        let target = json.data.find(item => item.name === key + "#")
        console.log("target", target)
        addBuildingTag(key, value[0], value[1], value[2], target.status, target.floor)
      })

      $('#loading_mask').hide()
      dataShow()

    }).catch(() => {
      $('#loading_mask').hide()
      dataShow()


    })
    let boxInnerCenter, h, topCenter
    var buildTopFloors = new Map //楼号-最高层数的散列表
    for (let a = 0; a < groupArr.length; a++) {
      if (groupArr[a].name.search("-") != -1) {
        numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

        if (buildTopFloors.get(numStrArr[0]) == null) {
          buildTopFloors.set(numStrArr[0], numStrArr[3])
        } else {
          if (parseInt(numStrArr[3]) > parseInt(buildTopFloors.get(numStrArr[0]))) {
            buildTopFloors.set(numStrArr[0], numStrArr[3])
          }
        }
      }
    }

    var peakArrMap = new Map() //楼号-顶楼各群组中心点数组的散列表
    buildTopFloors.forEach(function (value, key) {
      peakArrMap.set(key, [])
    })
    for (let a = 0; a < groupArr.length; a++) {

      if (groupArr[a].name.search("-") != -1) {
        numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

        if (numStrArr[3] == buildTopFloors.get(numStrArr[0])) { //最高层的某个群组
          groupArr[a].children[0].geometry.computeBoundingSphere()
          boxInnerCenter = groupArr[a].children[0].geometry.boundingSphere.center
          peakArrMap.get(numStrArr[0]).push({
            x: groupArr[a].position.x + boxInnerCenter.x,
            y: groupArr[a].position.y + boxInnerCenter.y,
            z: groupArr[a].position.z + boxInnerCenter.z
          })
        }
      }
    }

    var buildNoPositionMap = new Map() //楼号-楼号标签位置的散列表

    peakArrMap.forEach(function (value, key) {
      console.log(value)
      var x = 0, y = 0
      var peakArr = value
      for (h = 0; h < peakArr.length; h++) {
        x += peakArr[h].x;
        y += peakArr[h].y;
      }
      topCenter = [x / peakArr.length / 39.4, y / peakArr.length / 39.4, peakArr[0].z / 39.4]
      buildNoPositionMap.set(key, topCenter)
    })


    scene.add(mesh)
    render()

  })

}


// 添加底板
let planeGeometry = new THREE.PlaneGeometry(3000, 3000);
let planeMaterial = new THREE.MeshStandardMaterial({ color: 0xcccccc });
// 关闭deptchTest，使该材质无视渲染顺序，必定被渲染（防止重叠闪烁）
planeMaterial.depthTest = false
// planeMaterial.depthWrite = true
plane = new THREE.Mesh(planeGeometry, planeMaterial);
//设置平面需要接收阴影
plane.receiveShadow = true;
scene.add(plane);



/**
 * 光源设置
 */
// 第二个参数为光照强度，2倍
light = new THREE.DirectionalLight(0xFFFAF0, 0.1)

light.position.set(0, 0, 600); //点光源位置
light.castShadow = true;//开启阴影
light.shadow.mapSize.width = 4096; //阴影贴图宽度设置为2048像素
light.shadow.mapSize.height = 4096; //阴影贴图高度设置为2048像素
light.shadow.radius = 0;
//Set up shadow properties for the light
light.shadow.camera.near = 100;
light.shadow.camera.far = 3000;
light.shadow.camera.left = -300;
light.shadow.camera.right = 300;
light.shadow.camera.top = 300;
light.shadow.camera.bottom = -300;
light.shadow.color = '#ff0000'
// const light = new THREE.PointLight(0xFFFFFF);
// light.position.set(0, 0, 600); //点光源位置
scene.add(light);
// //环境光 由于环境光作用于所有的物体，所有的材质，所以环境光是没有方向的，也无法产生阴影效果。
ambLight = new THREE.AmbientLight(0xffffff, 0.9)
scene.add(ambLight);

// if (debug) {
//   const helper = new THREE.CameraHelper(light.shadow.camera);
//   scene.add(helper);
// }



/**
 * 相机设置
 */
let width = window.innerWidth; //窗口宽度
let height = window.innerHeight - $('#date-controller').height(); //窗口高度

var k = width / height; //窗口宽高比
var s = 300; //三维场景显示范围控制系数，系数越大，显示的范围越大
//创建相机对象
const camera = new THREE.PerspectiveCamera(fov, width / height, near, fear);
camera.position.set(400, 0, 500); //设置相机位置
camera.up.x = 0;
camera.up.y = 0;
camera.up.z = 1; //z轴向上
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)

/**
 * 创建渲染器对象
 */
const renderer = new THREE.WebGLRenderer({
  antialias: true, // true/false表示是否开启反锯齿
  alpha: true, // true/false 表示是否可以设置背景色透明
  logarithmicDepthBuffer: true,
  checkShaderErrors: false, //关闭检查提高性能
});
renderer.shadowMap.enabled = true
renderer.shadowMap.needsUpdate = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
renderer.setSize(width, height);//设置渲染区域尺寸
renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
renderer.setScissorTest(false)
renderer.info.autoReset = false
renderer.setPixelRatio(window.devicePixelRatio);//设置canvas的像素比为当前设备的屏幕像素比，避免高分屏下模糊
renderer.physicallyCorrectLights = false
document.getElementById('app').appendChild(renderer.domElement); //body元素中插入canvas对象


const controls = new OrbitControls(camera, renderer.domElement);//创建控件对象
//设置相机角度
//上下翻转的最大角度
controls.maxPolarAngle = 1.4;
//上下翻转的最小角度
controls.minPolarAngle = 0;
//是否允许缩放
controls.enableZoom = true;

controls.enableDamping = true
controls.maxZoom = 10
controls.minZoom = 0.8

//添加标签
//初始化CSS2渲染器
const labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(width, height);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.pointerEvents = 'none'
labelRenderer.domElement.style.boxSizing = 'border-box'
labelRenderer.domElement.style.top = 0;

document.body.appendChild(labelRenderer.domElement);


//render
function render() {

  controls.update()

  renderer.render(scene, camera);//执行渲染操作
  labelRenderer.render(scene, camera)

  //指南针

  //只考虑xoy平面，本项目x轴为南，y轴为东，即x轴负方向为正北方向
  //取与相机相反方向的向量，即目光所在的向量
  let dir = new THREE.Vector3(-camera.position.x, -camera.position.y, 0).normalize();

  let theta = Math.atan2(-dir.y, -dir.x);

  //指南针旋转
  $('#guide-wrap .compass').css({ 'transform': 'translate(-50%, -50%) rotate(' + THREE.Math.radToDeg(theta) + 'deg)' });
  animHandler = requestAnimationFrame(render);
}

function reset() {
  camera.position.set(400, 0, 500)
  controls.reset()
}



//添加标签文字材质
function addBuildingTag(text, x, y, z, status, lou) {
  let tagDiv = document.createElement('div')//创建div容器

  tagDiv.className = 'building_tag'
  tagDiv.innerHTML = `<span style="font-size: 12px;">${text}</span>#`
  if (status) {
    tagDiv.innerHTML += `${status}`
  }
  if (lou) {
    tagDiv.innerHTML += `&nbsp;<span style="font-size: 12px;">${lou}</span>F`
  }
  tagDiv.style.pointerEvents = 'all';
  tagDiv.style.color = '#111'
  tagDiv.style.boxSizing = 'border-box'

  tagDiv.style.fontSize = '10px'
  tagDiv.style.borderRadius = '7px'
  tagDiv.style.lineHeight = '14px'
  tagDiv.style.paddingLeft = '2px'
  tagDiv.style.paddingRight = '2px'
  tagDiv.style.border = '1px solid #111'

  tagDiv.style.verticalAlign = 'baseline'
  tagDiv.style.backgroundColor = fillStyleMap[status] + 'ee'
  if (!status) {
    tagDiv.style.backgroundColor = '#FFFFFFEE'
  }
  tagDiv.addEventListener('click', () => {
    // controls.reset()
    let _x = -y - dx
    let _y = x - dy
    let _z = z + 20
    let d = Math.sqrt(_x * _x + _y * _y)
    let r = Math.sqrt(d * d + _z * _z)


    let dis = 200

    let newD = (r + dis) / r * d


    let newX = newD / d * _x
    let newY = newD / d * _y

    let newZ = Math.sqrt(newD * newD + (r + dis) * (r + dis))

    console.log(_x, _y, _z, r, '    ', newX, newY, 0)

    camera.position.set(newX, newY, _z + 10)

  })

  let pointLabel = new CSS2DObject(tagDiv);
  pointLabel.position.set(-y - dx, x - dy, z + 20);
  // pointLabel.position.set(y - this.dx, x - this.dy, z + 10);
  // pointLabel.rotation.z = 90 / 180 * Math.PI
  scene.add(pointLabel)

}


//------白天黑夜切换------
$('.daylight-box span').on('click', function () {
  $(this).attr('class', 'select')
  $($('.daylight-box span')[($(this).index() + 1) % 2]).attr('class', '')
  switchDayLight($(this).html())
})

function switchDayLight(daylight) {
  setNoiseColor(daylight === '白天')
}




//------------------模型切换----------------------

$('#daes span').on('click', function () {
  $(this).attr('class', 'select')
  $($('#daes span')[($(this).index() + 1) % 2]).attr('class', '')


  //切换显示
  loadDae(loadUrl[$(this).index()].u)
  //重置到白天
  // switchDayLight("白天")

  $('.daylight-box span')[0].click()
})
//默认选中第一个
$($('#daes span')[0]).attr('class', 'select')
//--------------------end-----------------

//重置按钮
$('#btn_reset').on('click', () => {
  //默认选中第一个
  reset()
})

